<html>
  <head>
    <title>中国象棋</title>
    <meta charset="UTF-8" />
    <style>
      body {
        height: 100vh;
        margin: 0;
        padding: 0;
        /* 禁止选中文字 */
        -webkit-user-select: none;
        /* Chrome, Safari, Opera */
        -moz-user-select: none;
        /* Firefox */
        -ms-user-select: none;
        /* Internet Explorer/Edge */
        user-select: none;
      }
      table {
        margin: 10px;
        border-collapse: collapse;
      }
      table.board {
        background-color: white;
      }
      table,
      td.board {
        border: 1px solid black;
      }

      td {
        height: 65px;
        width: 65px;
        box-sizing: border-box;
      }

      div.pieces {
        margin: 0 auto;
        height: 50px;
        line-height: 50px;
        cursor: pointer;
        width: 50px;
        border: 1px solid #8b4513;
        border-radius: 25px;
        text-align: center;
        font-family: Cursive;
        font-size: 1.5em;
        background-color: #deb887;
      }
      div.red {
        color: red;
        background-color: #deb887;
      }
      div.green {
        color: #000;
        background-color: #deb887;
      }

      .btn {
        display: inline-block;
        padding: 6px 12px;
        margin-bottom: 0;
        font-size: 14px;
        font-weight: 400;
        line-height: 1.42857143;
        text-align: center;
        white-space: nowrap;
        vertical-align: middle;
        -ms-touch-action: manipulation;
        touch-action: manipulation;
        cursor: pointer;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
        background-image: none;
        border: 1px solid transparent;
        border-radius: 4px;
        margin-top: 10px;
      }
      .btn-primary {
        color: #fff;
        background-color: #428bca;
        border-color: #357ebd;
      }

      .btn-primary:hover {
        color: #fff;
        background-color: #3071a9;
        border-color: #285e8e;
      }
      .rotate {
        transform: scale(-1);
      }
      .rotate1 {
        transform: rotate(180deg) translate(-50%, -50%) !important;
        /* 旋转中心 */
        transform-origin: 0% 0%;
      }
    </style>
  </head>
  <body>
    <div style="display: flex; justify-content: center; align-items: center">
      <div id="chessboard" class="btn btn-primary">
        <div style="font-size: 20px">中国象棋</div>
        <div>旋转棋盘</div>
      </div>
    </div>
  </body>
  <script>
    /**
     * Skipped minification because the original files appears to be already minified.
     * Original file: /npm/msg-alert@1.0.0-beta.4/dist/msg-alert.js
     *
     * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
     */
    var message = (function () {
      "use strict";
      function t(t) {
        return t instanceof Element;
      }
      function e(t) {
        return "string" == typeof t;
      }
      function n(t, e) {
        var n = document.createElement(t);
        return e && (n.className = e), n;
      }
      function o(t, e) {
        var n = document.createElementNS("http://www.w3.org/2000/svg", t);
        for (var o in e) n.setAttribute(o, e[o]);
        return n;
      }
      function r(t) {
        var e =
          arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0;
        if (!(e < -1))
          for (var n = 0, o = e; o < t.length; o++) {
            var r = t[o];
            if (r) {
              var s = t[o - 1];
              s && (n = parseInt(s.style.top) + parseInt(s.offsetHeight)),
                (r.style.zIndex = r._msg.zIndex + o),
                (r.style.top = r._msg.offset + n + "px");
            }
          }
      }
      var s = "_msg-opacity",
        i = [],
        a = ["info", "success", "warn", "error"],
        c = n("style");
      function f(c) {
        e(c) && (c = { text: c });
        var l = Object.assign(
            { type: a[0], text: "", offset: 20, duration: 3e3 },
            c
          ),
          d = l.text,
          p = l.type,
          m = l.zIndex,
          g = l.offset,
          x = l.duration,
          v = l.customClass,
          h = l.html,
          y = l.showClose,
          _ = l.onClose,
          b = l.appendTo,
          w = n(
            "div",
            "_msg _msg-"
              .concat(p, " ")
              .concat(s, " ")
              .concat(v || "")
          );
        (w.id = (function (t) {
          t = t || 10;
          for (
            var e = function () {
                return Math.random().toString(36).slice(2);
              },
              n = e();
            n.length < t;

          )
            n += e();
          return n.slice(0, t);
        })()),
          (w._msg = {}),
          (w._msg.zIndex = m || f.zIndex),
          (w._msg.offset = g),
          i.push(w),
          setTimeout(function () {
            w.classList.remove(s);
          }, 100),
          x &&
            ((w._msg.t = setTimeout(function () {
              u(w, _);
            }, x)),
            (w.onmouseenter = function () {
              clearTimeout(w._msg.t);
            }),
            (w.onmouseleave = function () {
              w._msg.t = setTimeout(function () {
                u(w, _);
              }, x);
            }));
        var C,
          k = n("p");
        if (
          (w.appendChild(k), h ? (k.innerHTML = d) : (k.innerText = d), y || !x)
        ) {
          var T = (function () {
            var t = o("svg", {
                width: "16px",
                height: "16px",
                stroke: "currentColor",
                viewBox: "0 0 16 16",
                "stroke-linecap": "round",
              }),
              e = o("line", {
                x1: -7,
                y1: -7,
                x2: 6,
                y2: 6,
                transform: "translate(8.5 8.5)",
              }),
              n = o("line", {
                x1: 6,
                y1: -7,
                x2: -7,
                y2: 6,
                transform: "translate(8.5 8.5)",
              });
            return t.appendChild(e), t.appendChild(n), t;
          })();
          (T.onclick = function () {
            clearTimeout(w._msg.t),
              (w.onmouseenter = w.onmouseleave = T.onclick = null),
              u(w, _);
          }),
            w.appendChild(T);
        }
        t(b) ? (C = b) : e(b) && (C = document.querySelector(b)),
          t(C) || (C = document.body),
          C.appendChild(w),
          r(i);
      }
      (c.textContent =
        "._msg{left:50%;color:#909399;font-size:14px;width:300px;padding:16px 17px;position:fixed;line-height:1;letter-spacing:1px;word-wrap:break-word;word-break:break-all;border-radius:6px;border:1px solid #edf2fc;background-color:#edf2fc;transform:translateX(-50%);transition:opacity 0.3s,transform 0.5s,top 0.5s;}._msg p{margin:0;font-size:14px;padding-right:16px;}._msg svg{top:50%;right:15px;cursor:pointer;position:absolute;transform:translateY(-50%);}._msg-opacity{opacity:0;transform:translate(-50%,-100%);}._msg-success{background-color:#e1f3d8;border-color:#e1f3d8;color:#67c23a;}._msg-warn{background-color:#fdfce6;border-color:#fdfce6;color:#e6a23c;}._msg-error{background-color:#fef0f0;border-color:#fef0f0;color:#f56c6c;}"),
        document.head.appendChild(c),
        (f.zIndex = 1);
      var l = function (t) {
        f[a[t]] = function (n) {
          e(n) ? (n = { text: n, type: a[t] }) : (n.type = a[t]), f(n);
        };
      };
      for (var d in a) l(d);
      function u(t, e) {
        var n = i.findIndex(function (e) {
          return e.id === t.id;
        });
        i.splice(n, 1),
          r(i, n),
          "function" == typeof e && e(),
          t.classList.add(s),
          setTimeout(function () {
            t.parentElement.removeChild(t);
          }, 400);
      }
      return (
        (f.destroyAll = function () {
          for (
            var t = function (t) {
                var e = i[t];
                clearTimeout(e._msg.t),
                  e.classList.add(s),
                  setTimeout(function () {
                    e.parentElement.removeChild(e);
                  }, 400);
              },
              e = 0;
            e < i.length;
            e++
          )
            t(e);
          i.length = 0;
        }),
        f
      );
    })();
    //# sourceMappingURL=msg-alert.js.map
    // 默认 等价 message({type:'info',text:'这是一个段落'})
    // message("这是一个段落");
    // message.info("这是一个段落");
    // 成功 等价 message({type:'success',text:'success'})
    // message.success("success");
    // 警告 等价 message({type:'warn',text:'warn'})
    // message.warn("warn");
    // 错误 等价 message({type:'error',text:'error'})
    // message.error("error");
  </script>
  <script>
    const socket = new WebSocket("http://adfcb7.natappfree.cc");
    socket.onmessage = function (event) {
      if (typeof event.data === "string") {
        // 处理文本消息
        const data = JSON.parse(event.data);
        clickBoard();
      } else if (event.data instanceof Blob) {
        // 处理 Blob 数据
        const reader = new FileReader();
        reader.onload = function (e) {
          clickBoard(e);
        };
        reader.readAsText(event.data);
      }
    };

    //--------------------->棋盘的样子
    (function () {
      table = document.createElement("table");
      table.classList.add("board");
      tBody = document.createElement("tBody");
      for (var i = 0; i < 9; i++) {
        row = tBody.insertRow(i);
        for (var j = 0; j < 8; j++) {
          cell = row.insertCell(j);
          if (i != 4) {
            cell.classList.add("board");
          }
        }
      }
      table.style.width = "520px";
      table.style.height = "586px";
      table.style.position = "absolute";
      table.style.top = "50%";
      table.style.left = "50%";
      table.style.transform = "translate(-50%, -50%)";
      table.appendChild(tBody);
      document.body.appendChild(table);
    })();

    //--------------------->生成实际在使用的表格
    (function () {
      table = document.createElement("table");
      tBody = document.createElement("tBody");
      for (var i = 0; i < 10; i++) {
        row = tBody.insertRow(i);
        for (var j = 0; j < 9; j++) {
          cell = row.insertCell(j);
          cell.setAttribute("data-x", j);
          cell.setAttribute("data-y", i);
          cell.addEventListener("click", clickBoard, false);
        }
      }
      table.appendChild(tBody);
      table.style.width = "586px";
      table.style.height = "650px";
      table.style.position = "absolute";
      table.style.top = "50%";
      table.style.left = "50%";
      table.style.transform = "translate(-50%, -50%)";
      document.body.appendChild(table);
    })();

    //开始游戏字样
    (function () {
      beginText = document.createElement("h1");
      beginText.style.display = "inline";
      beginText.innerHTML = "重新开始游戏";
      beginText.addEventListener(
        "click",
        function (event) {
          // 二次确认
          if (confirm("确认要重新开始游戏吗？")) {
            socket.send(JSON.stringify({ type: "init" }));
            chessboard.init();
            turnText.style.color = "red";
            if (!chessboard.status) {
            }
          }
        },
        false
      );
      beginText.style.position = "absolute";
      beginText.style.bottom = "20px";
      beginText.style.left = "50%";
      beginText.style.transform = "translateX(-50%)";
      // 选中手势
      beginText.style.cursor = "pointer";
      document.body.appendChild(beginText);
    })();

    //走棋方展示
    (function () {
      turnText = document.createElement("h2");
      turnText.innerHTML = "红方";
      turnText.style.position = "absolute";
      turnText.style.top = "50px";
      turnText.style.left = "50%";
      turnText.style.transform = "translateX(-50%)";
      turnText.style.color = "red";
      document.body.appendChild(turnText);
    })();

    //-------------------->绑定三个事件

    //点击棋盘
    function clickBoard(event) {
      if (event.target.result) {
        const newData = JSON.parse(event.target.result);
        if (newData.type === "choose") {
          // 根据坐标选中棋子 chooseX chooseY
          chessboard.pieces[newData.chooseX][
            newData.chooseY
          ].piece.style.backgroundColor = "#B0E0E6";
          chessboard.curPiece =
            chessboard.pieces[newData.chooseX][newData.chooseY];
          chessboard.curPiece.piece.style.backgroundColor = "#B0E0E6";
          //阻止冒泡事件
          event.stopPropagation();
        }

        if (newData.type == "move") {
          // 移动棋子 moveX moveY
          chessboard.curPiece.move(newData.moveX, newData.moveY);
          //阻止冒泡事件
          event.stopPropagation();
        }

        // 取消选中棋子 cancel
        if (newData.type == "cancel") {
          chessboard.curPiece.piece.style.backgroundColor = "#deb887";
          chessboard.curPiece = null;
        }

        // 重新开始游戏 init
        if (newData.type == "init") {
          chessboard.init();
          chessboard.status = true;
          turnText.innerHTML = "红方";
          turnText.style.color = "red";
          //阻止冒泡事件
          event.stopPropagation();
        }
        return;
      }
      if (chessboard.status) {
        if (chessboard.curPiece) {
          var x = parseInt(this.getAttribute("data-x"));
          var y = parseInt(this.getAttribute("data-y"));
          socket.send(
            JSON.stringify({
              type: "move",
              moveX: x,
              moveY: y,
            })
          );
          //尝试移动棋子
          chessboard.curPiece.move(x, y);
        }
        // event.stopPropagation();
      } else {
        //游戏结束，什么也不做
        event.stopPropagation(); //阻止冒泡事件，因为冒泡也没有意义
      }
    }

    //选中棋子
    function choosePiece(event) {
      if (!chessboard.status) {
        message.warn("游戏已经结束，请重新开始游戏！");
        return;
      }
      if (chessboard.status) {
        if (
          chessboard.turn == !!this.getAttribute("data-team") &&
          !chessboard.curPiece
        ) {
          var x = parseInt(this.parentNode.getAttribute("data-x"));
          var y = parseInt(this.parentNode.getAttribute("data-y"));
          //选中棋子
          chessboard.curPiece = chessboard.pieces[x][y];
          chessboard.curPiece.piece.style.backgroundColor = "#B0E0E6";
          socket.send(
            JSON.stringify({
              type: "choose",
              chooseX: parseInt(this.parentNode.getAttribute("data-x")),
              chooseY: parseInt(this.parentNode.getAttribute("data-y")),
            })
          );
          //阻止冒泡事件
          //因为点击键盘事件是移动棋子位置事件，当前没有选中棋子，自然就不需要冒泡了
          event.stopPropagation();
        }
      } else {
        //游戏结束，什么也不做
        event.stopPropagation(); //阻止冒泡事件，因为冒泡也没有意义
      }
    }

    //取消选中棋子
    window.addEventListener(
      "click",
      function (event) {
        if (chessboard.status) {
          if (chessboard.curPiece) {
            chessboard.curPiece.piece.style.backgroundColor = "#deb887";

            socket.send(
              JSON.stringify({
                type: "cancel",
              })
            );
            chessboard.curPiece = null;
          }
        } else {
          //游戏结束，什么也不做
        }
      },
      false
    );

    //棋盘
    chessboard = {
      init: function () {
        for (i = 0; i < 9; i++) {
          this.pieces[i] = [];
        }
        if (this.copyPieces) {
          //直接拷贝this.copyPieces即可
          for (var i = 0; i < 9; i++) {
            if (this.copyPieces[i]) {
              for (var j = 0; j < 10; j++) {
                this.pieces[i][j] = this.copyPieces[i][j];
                this.pieces1[i][j] = this.copyPieces[i][j]; //用于保存一步以后的棋子布局
                if (table.rows[j].cells[i].childNodes.length) {
                  for (
                    var l = 0;
                    l < table.rows[j].cells[i].childNodes.length;
                    l++
                  ) {
                    table.rows[j].cells[i].removeChild(
                      table.rows[j].cells[i].childNodes[l]
                    );
                  }
                }
                if (this.pieces[i][j]) {
                  table.rows[j].cells[i].appendChild(this.pieces[i][j].piece); //棋盘放上棋子
                  this.pieces[i][j].positionX = i; //设置x轴
                  this.pieces[i][j].positionY = j; //设置y轴
                }
              }
            }
          }
        } else {
          //第一次运行，自己创建所有棋子
          {
            //红棋
            this.pieces[0][9] = new Car("CarR1", 0, 9, true);
            this.pieces[1][9] = new Horse("HorseR1", 1, 9, true);
            this.pieces[1][7] = new Cannon("CannonR1", 1, 7, true);
            this.pieces[2][9] = new Elephant("ElephantR1", 2, 9, true, "相");
            this.pieces[3][9] = new Bodyguards("BodyguardsR1", 3, 9, true);
            this.pieces[4][9] = new Boss("bossR", 4, 9, true, "帅");
            this.redBoss = this.pieces[4][9];
            this.pieces[5][9] = new Bodyguards("BodyguardsR2", 5, 9, true);
            this.pieces[6][9] = new Elephant("ElephantR2", 6, 9, true, "相");
            this.pieces[7][7] = new Cannon("CannonR2", 7, 7, true);
            this.pieces[7][9] = new Horse("HorseR2", 7, 9, true);
            this.pieces[8][9] = new Car("CarR2", 8, 9, true);

            this.pieces[0][6] = new Soldier("SoldierR1", 0, 6, true, "兵");
            this.pieces[2][6] = new Soldier("SoldierR2", 2, 6, true, "兵");
            this.pieces[4][6] = new Soldier("SoldierR3", 4, 6, true, "兵");
            this.pieces[6][6] = new Soldier("SoldierR4", 6, 6, true, "兵");
            this.pieces[8][6] = new Soldier("SoldierR5", 8, 6, true, "兵");

            //黑棋
            this.pieces[0][0] = new Car("CarG1", 0, 0, false);
            this.pieces[1][0] = new Horse("HorseG1", 1, 0, false);
            this.pieces[1][2] = new Cannon("CannonG1", 1, 2, false);
            this.pieces[2][0] = new Elephant("ElephantG1", 2, 0, false, "象");
            this.pieces[3][0] = new Bodyguards("BodyguardsG1", 3, 0, false);
            this.pieces[4][0] = new Boss("bossG", 4, 0, false, "将");
            this.greenBoss = this.pieces[4][0];
            this.pieces[5][0] = new Bodyguards("BodyguardsG2", 5, 0, false);
            this.pieces[6][0] = new Elephant("ElephantG2", 6, 0, false, "象");
            this.pieces[7][2] = new Cannon("CannonG2", 7, 2, false);
            this.pieces[7][0] = new Horse("HorseG2", 7, 0, false);
            this.pieces[8][0] = new Car("CarG2", 8, 0, false);

            this.pieces[0][3] = new Soldier("SoldierR1", 0, 3, false, "卒");
            this.pieces[2][3] = new Soldier("SoldierR2", 2, 3, false, "卒");
            this.pieces[4][3] = new Soldier("SoldierR3", 4, 3, false, "卒");
            this.pieces[6][3] = new Soldier("SoldierR4", 6, 3, false, "卒");
            this.pieces[8][3] = new Soldier("SoldierR5", 8, 3, false, "卒");
          }

          this.copyPieces = [];
          for (var i = 0; i < 9; i++) {
            if (this.pieces[i]) {
              this.copyPieces[i] = [];
              for (var j = 0; j < 10; j++) {
                this.copyPieces[i][j] = this.pieces[i][j];
                this.pieces1[i][j] = this.pieces[i][j];
              }
            }
          }

          //绑定事件单击
          var divs = document.getElementsByClassName("pieces");
          for (var i = 0; i < divs.length; i++) {
            divs[i].addEventListener("click", choosePiece, false);
          }
        }
        this.status = true;
        this.turn = true;
        turnText.innerHTML = "红方";
      },
      gameOver: function (winner) {
        if (winner) {
          // alert("红方胜利");
          message.success("红方胜利");
        } else {
          // alert("黑方胜利");
          message.success("黑方胜利");
        }
        this.status = false;
      },
      changeTurn: function () {
        this.turn = !this.turn;
        chessboard.curPiece.piece.style.backgroundColor = "#deb887";
        //当前选中棋子置换为null
        chessboard.curPiece = null;
        if (this.turn) {
          turnText.innerHTML = "红方";
          turnText.style.color = "red";
        } else {
          turnText.innerHTML = "黑方";
          turnText.style.color = "black";
        }

        if (beKillAnyWay(this.turn)) {
          // alert("绝杀！");
          message.error("绝杀！");
          chessboard.gameOver(!this.turn);
        }
      },
      status: true, //游戏的状态,true:正在玩，false:结束了
      redBoss: null,
      greenBoss: null,
      curPiece: null,
      pieces: [], //存放棋子当前布局状态
      pieces1: [[], [], [], [], [], [], [], [], []], //存放棋子走过一步后的布局状态
      copyPieces: null, //存放棋子布局的初始状态
      turn: true, //红先黑后,true:红
    };

    //检查跳的位置上是否有对手棋子
    //有：返回true
    //没有：返回false
    function checkEnemy(x, y) {
      if (
        chessboard.pieces[x][y] &&
        chessboard.pieces[x][y].team != this.team
      ) {
        return true;
      }
      return false;
    }

    //击杀对手棋子
    function killEnemy(x, y) {
      chessboard.pieces[x][y].beKill();
    }

    //是否将军
    function canKilBoss(x, y) {
      if (this.team) {
        for (var i = 0; i < chessboard.pieces.length; i++) {
          for (var j = 0; j < chessboard.pieces[i].length; j++) {
            if (
              chessboard.pieces[i][j] &&
              chessboard.pieces[i][j].team == this.team
            ) {
              if (
                chessboard.pieces[i][j].checkPath(
                  chessboard.greenBoss.positionX,
                  chessboard.greenBoss.positionY
                )
              ) {
                return true;
              }
            }
          }
        }
        return false;
      } else {
        for (var i = 0; i < chessboard.pieces.length; i++) {
          for (var j = 0; j < chessboard.pieces[i].length; j++) {
            if (
              chessboard.pieces[i][j] &&
              chessboard.pieces[i][j].team == this.team
            ) {
              if (
                chessboard.pieces[i][j].checkPath(
                  chessboard.redBoss.positionX,
                  chessboard.redBoss.positionY
                )
              ) {
                return true;
              }
            }
          }
        }
        return false;
      }
    }

    //被击杀
    function beKill() {
      chessboard.pieces[this.positionX][this.positionY] = null;
      chessboard.pieces1[this.positionX][this.positionY] = null;

      this.piece.parentNode.removeChild(this.piece);
      if (this.name == "将" || this.name == "帅") {
        chessboard.gameOver(!this.team);
      }
    }

    function check(x, y) {
      if (this.checkPath(x, y) && this.checkBoss(x, y)) {
        return true;
      }
      return false;
    }

    //检查是否被绝杀
    //会：返回true，不会：返回false
    function beKillAnyWay(turn) {
      for (var i = 0; i < 9; i++) {
        for (var j = 0; j < 10; j++) {
          if (chessboard.pieces[i][j] && chessboard.pieces[i][j].team == turn) {
            var paths = chessboard.pieces[i][j].pathCanGo();
            for (var l = 0; l < paths.length; l++) {
              if (
                !chessboard.pieces[i][j].canBeKilBoss(
                  paths[l]["x"],
                  paths[l]["y"]
                )
              ) {
                return false;
              }
            }
          }
        }
      }
      return true;
    }

    //走出这步后会不会送将
    //会：返回true，不会：返回false
    function canBeKilBoss(x, y) {
      //pieces1置换为1步以后的状态
      // if (false) {
      var tempPiece = chessboard.pieces1[x][y];
      chessboard.pieces1[this.positionX][this.positionY] = null;
      chessboard.pieces1[x][y] = this;

      //this也置换为一步以后的状态
      var tempX = this.positionX;
      var tempY = this.positionY;

      this.positionX = x;
      this.positionY = y;

      if (this.team) {
        for (var i = 0; i < 9; i++) {
          for (var j = 0; j < 10; j++) {
            if (chessboard.pieces1[i][j] && !chessboard.pieces1[i][j].team) {
              if (
                chessboard.pieces1[i][j].checkPath(
                  chessboard.redBoss.positionX,
                  chessboard.redBoss.positionY,
                  chessboard.pieces1
                )
              ) {
                //恢复之前的状态
                this.positionX = tempX;
                this.positionY = tempY;
                chessboard.pieces1[this.positionX][this.positionY] = this;
                chessboard.pieces1[x][y] = tempPiece;

                return true;
              }
            }
          }
        }
      } else {
        for (var i = 0; i < 9; i++) {
          for (var j = 0; j < 10; j++) {
            if (chessboard.pieces1[i][j] && chessboard.pieces1[i][j].team) {
              if (
                chessboard.pieces1[i][j].checkPath(
                  chessboard.greenBoss.positionX,
                  chessboard.greenBoss.positionY,
                  chessboard.pieces1
                )
              ) {
                //恢复之前的状态
                this.positionX = tempX;
                this.positionY = tempY;
                chessboard.pieces1[this.positionX][this.positionY] = this;
                chessboard.pieces1[x][y] = tempPiece;
                return true;
              }
            }
          }
        }
      }

      //恢复之前的状态
      this.positionX = tempX;
      this.positionY = tempY;

      chessboard.pieces1[this.positionX][this.positionY] = this;
      chessboard.pieces1[x][y] = null;
      // }
      return false;
    }

    //移动棋子
    function move(x, y) {
      if (this.check(x, y)) {
        //有对手的棋子，则吃掉对手棋子
        if (this.checkEnemy(x, y)) {
          killEnemy(x, y);
        }
        this.doMove(x, y);
        //换手
        chessboard.changeTurn();

        if (chessboard.status && this.canKilBoss(x, y)) {
          // alert("将军！");
          // 提示将军
          message.error("将军！");
        }
      }
    }

    //实际调整棋子的位置
    function doMove(x, y) {
      //棋子移动至这个位置
      this.piece.parentNode.removeChild(this.piece);
      table.rows[y].cells[x].appendChild(this.piece);

      //二维数组处放置当前棋子
      chessboard.pieces[x][y] = this;
      chessboard.pieces[this.positionX][this.positionY] = null;

      //一步后的二维数组同步更新
      chessboard.pieces1[x][y] = this;
      chessboard.pieces1[this.positionX][this.positionY] = null;

      this.positionX = x;
      this.positionY = y;
    }

    //棋子的父类，定义了一些方法，供继承使用（但是发现这个继承用处不大，甚至有些负作用）
    function Pieces() {
      this.checkEnemy = checkEnemy;
      this.killEnemy = killEnemy;
      this.beKill = beKill;
      this.canKilBoss = canKilBoss;
      this.canBeKilBoss = canBeKilBoss;
      this.move = move;
      this.doMove = doMove;
      this.checkBoss = checkBoss;
      this.check = check;
    }

    //判断车的位置是否合法
    function checkCarPath(x, y, chessArr) {
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      if (
        (this.positionX == x && this.positionY != y) ||
        (this.positionX != x && this.positionY == y)
      ) {
        //前进路线中不能有任何障碍
        if (this.positionX == x) {
          for (
            var i = Math.min(this.positionY, y) + 1;
            i < Math.max(this.positionY, y);
            i++
          ) {
            if (chessArr) {
              if (chessArr[x][i]) {
                return false;
              }
            } else {
              if (chessboard.pieces[x][i]) {
                return false;
              }
            }
          }
        } else {
          for (
            var i = Math.min(this.positionX, x) + 1;
            i < Math.max(this.positionX, x);
            i++
          ) {
            if (chessArr) {
              if (chessArr[i][y]) {
                return false;
              }
            } else {
              if (chessboard.pieces[i][y]) {
                return false;
              }
            }
          }
        }
        return true;
      }
      return false;
    }

    //车可以移动的位置
    function pathCanGo_car(chessArr) {
      var paths = [];

      //x不变，y轴上可以移动的位置
      for (var i = 0; i < 9; i++) {
        if (i != this.positionY && this.check(this.positionX, i)) {
          paths.push({ x: this.positionX, y: i });
        }
      }
      //y不变，x轴上可以移动的位置
      for (var i = 0; i < 10; i++) {
        if (i != this.positionX && this.check(i, this.positionY)) {
          paths.push({ x: i, y: this.positionY });
        }
      }
      return paths;
    }

    //车
    function Car(nID, nX, nY, nTeam) {
      this.name = "车";
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;
      this.checkPath = checkCarPath;
      this.pathCanGo = pathCanGo_car;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //判断马的位置是否合法
    function checkHorsePath(x, y, chessArr) {
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      //马走日字
      if (
        Math.abs(x - this.positionX) == 2 &&
        Math.abs(y - this.positionY) == 1
      ) {
        //蹩马腿
        if (chessboard.pieces[(x + this.positionX) / 2][this.positionY]) {
          return false;
        }
        return true;
      }
      if (
        Math.abs(x - this.positionX) == 1 &&
        Math.abs(y - this.positionY) == 2
      ) {
        //蹩马腿
        if (chessboard.pieces[this.positionX][(y + this.positionY) / 2]) {
          return false;
        }
        return true;
      }
      return false;
    }

    //马可以移动的位置
    function pathCanGo_Horse() {
      var paths = [];
      //右二下一
      if (this.check(this.positionX + 2, this.positionY + 1)) {
        paths.push({ x: this.positionX + 2, y: this.positionY + 1 });
      }
      //右二上一
      if (this.check(this.positionX + 2, this.positionY - 1)) {
        paths.push({ x: this.positionX + 2, y: this.positionY - 1 });
      }
      //左二下一
      if (this.check(this.positionX - 2, this.positionY + 1)) {
        paths.push({ x: this.positionX - 2, y: this.positionY + 1 });
      }
      //左二上一
      if (this.check(this.positionX - 2, this.positionY - 1)) {
        paths.push({ x: this.positionX - 2, y: this.positionY - 1 });
      }
      //右一下二
      if (this.check(this.positionX + 1, this.positionY + 2)) {
        paths.push({ x: this.positionX + 1, y: this.positionY + 2 });
      }
      //右一上二
      if (this.check(this.positionX + 1, this.positionY - 2)) {
        paths.push({ x: this.positionX + 1, y: this.positionY - 2 });
      }
      //左一下二
      if (this.check(this.positionX - 1, this.positionY + 2)) {
        paths.push({ x: this.positionX - 1, y: this.positionY + 2 });
      }
      //左一上二
      if (this.check(this.positionX - 1, this.positionY - 2)) {
        paths.push({ x: this.positionX - 1, y: this.positionY - 2 });
      }
      return paths;
    }

    //马
    function Horse(nID, nX, nY, nTeam) {
      this.name = "马";
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;
      this.checkPath = checkHorsePath;
      this.pathCanGo = pathCanGo_Horse;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //判断象的位置是否合法
    function checkElephantPath(x, y, chessArr) {
      // if (!(this.name == "相" || this.name == "象")) {
      //   return false;
      // }
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      //不能过河
      if (this.team) {
        if (y < 5) {
          return false;
        }
      } else {
        if (y > 4) {
          return false;
        }
      }

      //象走田字
      if (
        Math.abs(x - this.positionX) == 2 &&
        Math.abs(y - this.positionY) == 2
      ) {
        //蹩象腿
        if (
          !chessboard.pieces[(x + this.positionX) / 2][(y + this.positionY) / 2]
        ) {
          return true;
        }
      }
      return false;
    }

    //象可以移动的位置
    function pathCanGo_Elephant() {
      var paths = [];
      //右二下二
      if (this.check(this.positionX + 2, this.positionY + 2)) {
        paths.push({ x: this.positionX + 2, y: this.positionY + 2 });
      }
      //右二上二
      if (this.check(this.positionX + 2, this.positionY - 2)) {
        paths.push({ x: this.positionX + 2, y: this.positionY - 2 });
      }
      //左二下二
      if (this.check(this.positionX - 2, this.positionY + 2)) {
        paths.push({ x: this.positionX - 2, y: this.positionY + 2 });
      }
      //左二上二
      if (this.check(this.positionX - 2, this.positionY - 2)) {
        paths.push({ x: this.positionX - 2, y: this.positionY - 2 });
      }
      return paths;
    }

    //象
    function Elephant(nID, nX, nY, nTeam, name) {
      this.name = name;
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;
      this.checkPath = checkElephantPath;
      this.pathCanGo = pathCanGo_Elephant;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //判断士的位置是否合法
    function checkBodyguardsPath(x, y, chessArr) {
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      //x轴不能出九宫格
      if (x != 3 && x != 4 && x != 5) {
        return false;
      }

      //y轴不能出九宫格
      if (this.team) {
        if (y < 7) {
          return false;
        }
      } else {
        if (y > 2) {
          return false;
        }
      }

      //士斜着走一步
      if (
        Math.abs(x - this.positionX) == 1 &&
        Math.abs(y - this.positionY) == 1
      ) {
        return true;
      }
      return false;
    }

    //士可以移动的位置
    function pathCanGo_Bodyguards() {
      var paths = [];
      if (this.check(this.positionX + 1, this.positionY + 1)) {
        paths.push({ x: this.positionX + 1, y: this.positionY + 1 });
      }
      if (this.check(this.positionX + 1, this.positionY - 1)) {
        paths.push({ x: this.positionX + 1, y: this.positionY - 1 });
      }
      if (this.check(this.positionX - 1, this.positionY + 1)) {
        paths.push({ x: this.positionX - 1, y: this.positionY + 1 });
      }
      if (this.check(this.positionX - 1, this.positionY - 1)) {
        paths.push({ x: this.positionX - 1, y: this.positionY - 1 });
      }
      return paths;
    }

    //士，找不到合适的单词，构造器意为保镖
    function Bodyguards(nID, nX, nY, nTeam) {
      this.name = "士";
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;
      this.checkPath = checkBodyguardsPath;
      this.pathCanGo = pathCanGo_Bodyguards;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //将/帅的位置是否合法
    function checkBossPath(x, y, chessArr) {
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      if (x != 3 && x != 4 && x != 5) {
        return false;
      }
      if (this.team) {
        if (y < 7) {
          return false;
        }
      } else {
        if (y > 2) {
          return false;
        }
      }
      if (
        Math.abs(x - this.positionX) == 1 &&
        Math.abs(y - this.positionY) == 0
      ) {
        return true;
      }
      if (
        Math.abs(x - this.positionX) == 0 &&
        Math.abs(y - this.positionY) == 1
      ) {
        return true;
      }
      return false;
    }

    //将可以移动的位置
    function pathCanGo_Boss() {
      var paths = [];
      if (this.check(this.positionX + 1, this.positionY)) {
        paths.push({ x: this.positionX + 1, y: this.positionY });
      }
      if (this.check(this.positionX - 1, this.positionY)) {
        paths.push({ x: this.positionX - 1, y: this.positionY });
      }
      if (this.check(this.positionX, this.positionY + 1)) {
        paths.push({ x: this.positionX, y: this.positionY + 1 });
      }
      if (this.check(this.positionX, this.positionY - 1)) {
        paths.push({ x: this.positionX, y: this.positionY - 1 });
      }
      return paths;
    }

    //将，帅
    function Boss(nID, nX, nY, nTeam, name) {
      this.name = name;
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;

      this.checkPath = checkBossPath;
      this.pathCanGo = pathCanGo_Boss;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //兵/卒的位置是否合法
    function checkSoldierPath(x, y, chessArr) {
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      if (this.team) {
        //不能后退
        if (y > this.positionY) {
          return false;
        }
        //前进，合法
        if (
          Math.abs(x - this.positionX) == 0 &&
          Math.abs(y - this.positionY) == 1
        ) {
          return true;
        }
        //过河后可以横向移动，然而也只能走一步
        if (this.positionY < 5) {
          if (
            Math.abs(x - this.positionX) == 1 &&
            Math.abs(y - this.positionY) == 0
          ) {
            return true;
          }
        }
      } else {
        //不能后退
        if (y < this.positionY) {
          return false;
        }
        //前进，合法
        if (
          Math.abs(x - this.positionX) == 0 &&
          Math.abs(y - this.positionY) == 1
        ) {
          return true;
        }
        //过河后可以横向移动，然而也只能走一步
        if (this.positionY > 4) {
          if (
            Math.abs(x - this.positionX) == 1 &&
            Math.abs(y - this.positionY) == 0
          ) {
            return true;
          }
        }
      }

      return false;
    }

    //兵/卒可以移动的位置
    function pathCanGo_Soldier() {
      var paths = [];
      if (this.team) {
        if (this.check(this.positionX, this.positionY - 1)) {
          paths.push({ x: this.positionX, y: this.positionY - 1 });
        }
        if (this.positionY < 5) {
          if (this.check(this.positionX + 1, this.positionY)) {
            paths.push({ x: this.positionX + 1, y: this.positionY });
          }
          if (this.check(this.positionX - 1, this.positionY)) {
            paths.push({ x: this.positionX - 1, y: this.positionY });
          }
        }
      } else {
        if (this.check(this.positionX, this.positionY + 1)) {
          paths.push({ x: this.positionX, y: this.positionY + 1 });
        }
        if (this.positionY > 4) {
          if (this.check(this.positionX + 1, this.positionY)) {
            paths.push({ x: this.positionX + 1, y: this.positionY });
          }
          if (this.check(this.positionX - 1, this.positionY)) {
            paths.push({ x: this.positionX - 1, y: this.positionY });
          }
        }
      }
      return paths;
    }

    //兵
    function Soldier(nID, nX, nY, nTeam, name) {
      this.name = name;
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;
      this.checkPath = checkSoldierPath;
      this.pathCanGo = pathCanGo_Soldier;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //炮的位置是否合法
    function checkCannonPath(x, y, chessArr) {
      if (x < 0 || x > 8 || y < 0 || y > 9) {
        return false;
      }
      if (chessArr) {
        if (chessArr[x][y] && chessArr[x][y].team == this.team) {
          return false;
        }
      } else {
        if (
          chessboard.pieces[x][y] &&
          chessboard.pieces[x][y].team == this.team
        ) {
          return false;
        }
      }
      //炮走直线
      if (this.positionX == x || this.positionY == y) {
        var count = 0; //计数路线上的障碍
        if (this.positionX == x) {
          count = count2Piece("y", this.positionY, y, x, chessArr);
        } else {
          count = count2Piece("x", this.positionX, x, y, chessArr);
        }
        //没有障碍，切目标位置没有棋子，合法
        if (chessArr) {
          if (count == 0 && !chessArr[x][y]) {
            return true;
          }
          //有一个障碍
          if (count == 1) {
            //且目标位置上有对手棋子，合法
            if (chessArr[x][y] && chessArr[x][y].team != this.team) {
              return true;
            }
          }
        } else {
          if (count == 0 && !chessboard.pieces[x][y]) {
            return true;
          }
          //有一个障碍
          if (count == 1) {
            //且目标位置上有对手棋子，合法
            if (
              chessboard.pieces[x][y] &&
              chessboard.pieces[x][y].team != this.team
            ) {
              return true;
            }
          }
        }
      }
      //其余情况均不合法
      return false;
    }

    //泡可以移动的位置
    function pathCanGo_Cannon() {
      var paths = [];
      for (var i = 0; i < 10; i++) {
        if (i != this.positionY && this.check(this.positionX, i)) {
          paths.push({ x: this.positionX, y: i });
        }
      }
      for (var i = 0; i < 9; i++) {
        if (i != this.positionX && this.check(i, this.positionY)) {
          paths.push({ x: i, y: this.positionY });
        }
      }
      return paths;
    }

    //炮
    function Cannon(nID, nX, nY, nTeam) {
      this.name = "炮";
      this.ID = nID;
      this.positionX = nX;
      this.positionY = nY;
      this.team = !!nTeam;
      this.checkPath = checkCannonPath;
      this.pathCanGo = pathCanGo_Cannon;
      this.piece = createPieces(
        this.name,
        this.positionX,
        this.positionY,
        this.name,
        this.team
      );
    }

    //检查老将问题
    function checkBoss(x, y, chessArr) {
      if (this.canBeKilBoss(x, y, chessArr)) {
        return false;
      }
      if (this.name == "将" || this.name == "帅") {
        //将要移动的是将
        if (this.team) {
          //帅
          if (x != chessboard.greenBoss.positionX) {
            return true;
          }
          var count = count2Piece(
            "y",
            y,
            chessboard.greenBoss.positionY,
            x,
            chessArr
          );
          return count > 0;
        } else {
          //将
          if (x != chessboard.redBoss.positionX) {
            return true;
          }
          var count = count2Piece(
            "y",
            y,
            chessboard.redBoss.positionY,
            x,
            chessArr
          );
          return count > 0;
        }
      } else {
        //将要移动的不是将

        //两方的将不在同一条线，通过
        if (chessboard.redBoss.positionX != chessboard.greenBoss.positionX) {
          return true;
        }

        var count = count2Piece(
          "y",
          chessboard.redBoss.positionY,
          chessboard.greenBoss.positionY,
          chessboard.redBoss.positionX,
          chessArr
        );

        //新的位置在两个老将的x轴上，且y轴在两个老将之间
        if (
          x == chessboard.redBoss.positionX &&
          y < chessboard.redBoss.positionY &&
          y > chessboard.greenBoss.positionY
        ) {
          count++;
        }
        //旧的位置在两个老将的x轴上，且y轴在两个老将之间
        if (
          this.positionX == chessboard.redBoss.positionX &&
          y < chessboard.redBoss.positionY &&
          y > chessboard.greenBoss.positionY
        ) {
          count--;
        }
        return count > 0;
      }
    }
    /**
        计算在一条线上的两个棋子“之间”的棋子数量
        @param XOrY 计算x轴还是y轴上的棋子数量
        @param a1 要计算的轴上的两点中的一点
        @param a2 要计算的轴上的两点中的一点
        @param a3 不需要计算的轴上的值
        @param chessArr 要在哪个棋子布局上计算
    */
    function count2Piece(XOrY, a1, a2, a3, chessArr) {
      var count = 0;
      if (XOrY == "x" || XOrY == "X") {
        for (var i = Math.min(a1, a2) + 1; i < Math.max(a1, a2); i++) {
          if (chessArr) {
            if (chessArr[i][a3]) {
              ++count;
            }
          } else {
            if (chessboard.pieces[i][a3]) {
              ++count;
            }
          }
        }
      } else {
        for (var i = Math.min(a1, a2) + 1; i < Math.max(a1, a2); i++) {
          if (chessArr) {
            if (chessArr[a3][i]) {
              ++count;
            }
          } else {
            if (chessboard.pieces[a3][i]) {
              ++count;
            }
          }
        }
      }
      return count;
    }

    //在dom中创建棋子
    function createPieces(ID, x, y, name, team) {
      var div = document.createElement("div");
      div.setAttribute("data-team", team ? "red" : "");
      div.classList.add("pieces");
      div.classList.add(team ? "red" : "green");
      div.appendChild(document.createTextNode(name));
      tBody.rows[y].cells[x].appendChild(div);
      return div;
    }

    var p = new Pieces();
    Car.prototype = p;
    Horse.prototype = p;
    Elephant.prototype = p;
    Bodyguards.prototype = p;
    Boss.prototype = p;
    Soldier.prototype = p;
    Cannon.prototype = p;

    chessboard.init();
  </script>

  <script>
    let flag = true;
    window.onload = function () {
      // 旋转棋盘 180°
      const chessboard = document.querySelector("#chessboard");
      const tables = document.querySelectorAll("table");
      const piecess = document.querySelectorAll(".pieces");
      chessboard.addEventListener("click", function () {
        if (flag) {
          flag = false;
          tables.forEach(function (table) {
            table.classList.add("rotate1");
          });
          piecess.forEach(function (piece) {
            piece.classList.add("rotate");
          });
        } else {
          flag = true;
          tables.forEach(function (table) {
            table.classList.remove("rotate1");
          });
          piecess.forEach(function (piece) {
            piece.classList.remove("rotate");
          });
        }
      });
    };
  </script>
</html>
